package com.lingo.mgr.websocket;

import com.alibaba.fastjson.JSONObject;
import com.lingo.mgr.listener.IseClientListener;
import com.lingo.mgr.service.IAudioService;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.yeauty.annotation.*;
import org.yeauty.pojo.Session;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@ServerEndpoint(path = "/ws/{userId}",host = "${ws.host}",port = "${ws.port}",maxFramePayloadLength="99999999")
@Slf4j
@Component
public class LingoWebSocket {

    /**
     * concurrent包的线程安全Map，用来存放每个客户端对应的MyWebSocket对象。
     * 若要实现服务端与单一客户端通信的话，可以使用Map来存放，其中Key可以为用户标识
     */
    public static Map<String, Session> webSocketMap = new ConcurrentHashMap<>();

    @Autowired
    private IAudioService iAudioService;



    @OnOpen
    public void onOpen(Session session,  @PathVariable("userId") String userId){
        log.info("new connection :{}",userId);
        webSocketMap.put(userId,session);
    }

    @OnClose
    public void onClose(Session session) throws IOException {
        log.info("one connection closed");
    }

    @OnError
    public void onError(Session session, Throwable throwable) {
        throwable.printStackTrace();
    }

    @OnMessage
    public void onMessage(Session session, String message) {
        log.info(message);
        session.sendText("Hello Netty!");
    }

    @OnBinary
    public void onBinary(Session session, byte[] bytes,@PathVariable("userId") String userId) {
        log.info("接收到文件流信息:{}",bytes.length);
        byte[] hash = calculateHash(bytes);

        // 将哈希值进行校验
        boolean isValid = verifyHash(bytes, hash);

        if (isValid) {
            log.info("音频数据完整且正确。");
        } else {
            log.info("音频数据可能存在损坏或篡改。");
        }
        iAudioService.audioEvent(userId,bytes);
        session.sendBinary(bytes);
    }

    public void sendBinary(String userId , byte[] bytes){
        Session session = webSocketMap.get(userId);
        if (!ObjectUtils.isEmpty(session)) {
            if (session.isOpen()) {
                session.sendBinary(bytes);
            } else {
                log.error("session 已关闭，消息发送失败");
            }
        } else {
            log.error("session 不存在，消息发送失败");
        }
    }

    @OnEvent
    public void onEvent(Session session, Object evt) {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent idleStateEvent = (IdleStateEvent) evt;
            switch (idleStateEvent.state()) {
                case READER_IDLE:
                    log.info("read idle");
                    break;
                case WRITER_IDLE:
                    log.info("write idle");
                    break;
                case ALL_IDLE:
                    log.info("all idle");
                    break;
                default:
                    break;
            }
        }
    }

    private static byte[] calculateHash(byte[] data) {
        try {
            // 创建 SHA-256 哈希算法实例
            MessageDigest md = MessageDigest.getInstance("SHA-256");

            // 计算数据的哈希值
            return md.digest(data);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        return null;
    }

    private static boolean verifyHash(byte[] data, byte[] hash) {
        // 重新计算数据的哈希值
        byte[] recalculatedHash = calculateHash(data);

        // 比较重新计算的哈希值和传入的哈希值是否相同
        return MessageDigest.isEqual(hash, recalculatedHash);
    }

}

